#ifndef __PISTON_BLOCK_H__
#define __PISTON_BLOCK_H__

#include "Block.hpp"

namespace PocketSurvival
{
	enum class PistonMode
	{
		Pushing,
		Pulling,
		StrictPulling
	};

    // 活塞
    class PistonBlock : public Block
    {
    public:
        static constexpr int32_t Index()
        {
            return 237;
        }
        virtual int32_t getIndex() override; 
        virtual const std::string &getBlockName() override;

        virtual void getCreativeValues(std::vector<int32_t> &blockVec) override;
        virtual void getDropValues(int32_t oldValue, int32_t newValue, int32_t toolLevel, std::vector<BlockDropValue> &dropValues) override;
    
        virtual BlockPlacementData getPlacementValue(ComponentMiner *componentMiner, int32_t value, const TerrainRaycastResult &raycastResult) override;

		static inline bool GetIsExtended(int32_t data);
		static inline int32_t SetIsExtended(int32_t data, bool isExtended);
		static inline PistonMode GetMode(int32_t data);
		static inline int32_t SetMode(int32_t data, PistonMode mode);
		static inline int32_t GetFace(int32_t data);
		static inline int32_t SetFace(int32_t data, int32_t face);
		static inline int32_t GetMaxExtension(int32_t data);
		static inline int32_t SetMaxExtension(int32_t data, int32_t maxExtension);
		static inline int32_t GetPullCount(int32_t data);
		static inline int32_t SetPullCount(int32_t data, int32_t pullCount);
		static inline int32_t GetSpeed(int32_t data);
		static inline int32_t SetSpeed(int32_t data, int32_t speed);
		static inline bool GetWaitingForTerrain(int32_t data);
		static inline int32_t SetWaitingForTerrain(int32_t data, bool value);
    };

	inline bool PistonBlock::GetIsExtended(int32_t data)
	{
		return (data & 1) != 0;
	}

	inline int32_t PistonBlock::SetIsExtended(int32_t data, bool isExtended)
	{
		return (data & -2) | (isExtended ? 1 : 0);
	}

	inline PistonMode PistonBlock::GetMode(int32_t data)
	{
		return (PistonMode)((data >> 1) & 3);
	}

	inline int32_t PistonBlock::SetMode(int32_t data, PistonMode mode)
	{
		return (data & -7) | (((int32_t)mode & 3) << 1);
	}

	inline int32_t PistonBlock::GetFace(int32_t data)
	{
		return (data >> 3) & 7;
	}

	inline int32_t PistonBlock::SetFace(int32_t data, int32_t face)
	{
		return (data & -57) | ((face & 7) << 3);
	}

	inline int32_t PistonBlock::GetMaxExtension(int32_t data)
	{
		return (data >> 6) & 7;
	}

	inline int32_t PistonBlock::SetMaxExtension(int32_t data, int32_t maxExtension)
	{
		return (data & -449) | ((maxExtension & 7) << 6);
	}

	inline int32_t PistonBlock::GetPullCount(int32_t data)
	{
		return (data >> 9) & 7;
	}

	inline int32_t PistonBlock::SetPullCount(int32_t data, int32_t pullCount)
	{
		return (data & -3585) | ((pullCount & 7) << 9);
	}

	inline int32_t PistonBlock::GetSpeed(int32_t data)
	{
		return (data >> 12) & 7;
	}

	inline int32_t PistonBlock::SetSpeed(int32_t data, int32_t speed)
	{
		return (data & -12289) | ((speed & 3) << 12);
	}

	inline bool PistonBlock::GetWaitingForTerrain(int32_t data)
    {
		return (data >> 14) != 0;
    }

	inline int32_t PistonBlock::SetWaitingForTerrain(int32_t data, bool value)
    {
		return (data & ~(1 << 14)) | ((value ? 1 : 0) << 14);
	}

} // namespace PocketSurvival


#endif
